#pragma once

#include "../umlmodel_global.h"

#include <memory>
#include <vector>

#include "ValueSpecification.h"

using std::make_shared;
using std::shared_ptr;
using std::vector;

namespace uml {
class Behavior;
class Parameter;

/// <summary>
/// OpaqueExpression
/// An OpaqueExpression is a ValueSpecification that specifies the computation of a
/// collection of values either in terms of a UML Behavior or based on a textual
/// statement in a language other than UML
/// </summary>
class UMLMODEL_EXPORT OpaqueExpression : public ValueSpecification {

public: // Constructors and destructors
    explicit OpaqueExpression(const QString& umlType="uml::OpaqueExpression");

public: // JsonSerializable override
    void fromJson(const QJsonObject& json, QStringList& errorList) override;
    void toJson(QJsonObject& json) override;

public: // Methods
    /// <summary>
    /// isIntegral
    /// The query isIntegral() tells whether an expression is intended to produce an
    /// Integer.
    /// </summary>
    virtual bool isIntegral() const;

    /// <summary>
    /// isNonNegative
    /// The query isNonNegative() tells whether an integer expression has a non-negative
    /// value.
    /// </summary>
    virtual bool isNonNegative() const;

    /// <summary>
    /// isPositive
    /// The query isPositive() tells whether an integer expression has a positive value.
    /// </summary>
    virtual bool isPositive() const;

    /// <summary>
    /// value
    /// The query value() gives an integer value for an expression intended to produce
    /// one.
    /// </summary>
    virtual int value() const;

public: // Properties
    /// <summary>
    /// behavior getter
    /// Specifies the behavior of the OpaqueExpression as a UML Behavior.
    /// </summary>
    shared_ptr<Behavior> behavior() const;

    /// <summary>
    /// behavior setter
    /// Specifies the behavior of the OpaqueExpression as a UML Behavior.
    /// </summary>
    void setBehavior(shared_ptr<Behavior> value);

    /// <summary>
    /// bodys getter
    /// A textual definition of the behavior of the OpaqueExpression, possibly in
    /// multiple languages.
    /// </summary>
    vector<QString>& bodys();

    /// <summary>
    /// languages getter
    /// Specifies the languages used to express the textual bodies of the
    /// OpaqueExpression.  Languages are matched to body Strings by order. The
    /// interpretation of the body depends on the languages. If the languages are
    /// unspecified, they may be implicit from the expression body or the context.
    /// </summary>
    vector<QString>& languages();

    /// <summary>
    /// result getter
    /// If an OpaqueExpression is specified using a UML Behavior, then this refers to
    /// the single required return Parameter of that Behavior. When the Behavior
    /// completes execution, the values on this Parameter give the result of evaluating
    /// the OpaqueExpression.
    /// </summary>
    shared_ptr<Parameter> result() const;

    /// <summary>
    /// result setter
    /// If an OpaqueExpression is specified using a UML Behavior, then this refers to
    /// the single required return Parameter of that Behavior. When the Behavior
    /// completes execution, the values on this Parameter give the result of evaluating
    /// the OpaqueExpression.
    /// </summary>
    void setResult(shared_ptr<Parameter> value);

private: // Fields
    /// <summary>
    /// behavior
    /// Specifies the behavior of the OpaqueExpression as a UML Behavior.
    /// </summary>
    shared_ptr<Behavior> behavior_;

    /// <summary>
    /// bodys
    /// A textual definition of the behavior of the OpaqueExpression, possibly in
    /// multiple languages.
    /// </summary>
    vector<QString> bodys_;

    /// <summary>
    /// languages
    /// Specifies the languages used to express the textual bodies of the
    /// OpaqueExpression.  Languages are matched to body Strings by order. The
    /// interpretation of the body depends on the languages. If the languages are
    /// unspecified, they may be implicit from the expression body or the context.
    /// </summary>
    vector<QString> languages_;

    /// <summary>
    /// result
    /// If an OpaqueExpression is specified using a UML Behavior, then this refers to
    /// the single required return Parameter of that Behavior. When the Behavior
    /// completes execution, the values on this Parameter give the result of evaluating
    /// the OpaqueExpression.
    /// </summary>
    shared_ptr<Parameter> result_;

};

} // namespace uml
